#ifndef WATERCRAFT_SERVER_H
#define WATERCRAFT_SERVER_H

#include <map>
#include <stack>
#include <cstdio>
#include <deque>
#include <set>

#include "SDL/SDL_net.h"
#include "SDL/SDL_thread.h"
#include "SDL/SDL_mutex.h"

#include "constants.h"
#include "client.h"
#include "level.h"
#include "config.h"
#include "spleef.h"

class Spleef;

class Server
{
	public:
		Server();
		~Server();
		
		static int main_loop_run(void* unused);
		static int secondary_loop_run(void* unused);
	
		void set_box(int x,int y,int z, int x2, int y2, int z2, char type, int thickness=0, int type2 = -1); // Type2 is the filling.
		void set_block(int x, int y, int z, char type);
	
		int send_block(short x, short y, short z, char type, int i);
		int send_spawn(int id, std::string name, short x, short y, short z, char rx, char ry, int i);
		int send_player_update(int id, short x, short y, short z, char rx, char ry, int i);
		int send_player_update_small(int id, char x, char y, char z, char rx, char ry, int i);
		int send_player_movement(int id, char x, char y, char z, int i);
		int send_player_rot(int id, char rx, char ry, int i);
		int send_player_delete(int id, int i);
		int send_chat(int id, char* msg, int i);
		int send_kick(char* reason, int i);		
		
		void send_chat_all(int id, char* msg);
		void send_player_delete_all(int id);
		void send_player_update_all(int id, short x, short y, short z, char rx, char ry);
		void send_block_all(short x, short y, short z, char type, int exclude=-1);
		
		void find_players(int x, int y, int z, int x2, int y2, int z2, std::set<char>* ids);
		int is_connected(int id);
		void move_player(int x, int y, int z, int rx, int ry, int id);
		
		std::string get_player_name(int id);
		void log(char* name);
		
	private:
		int main_loop();
		int secondary_loop();
		
		int handle_movement(int id);
		int parse_command(int id, char* msg);
        void handle_incoming_data(char* buffer, int id, char len);
		void handle_disconnect(int id);		
		
		int connect_client(int id, TCPsocket socket);
		
		char* get_time();
		
		Spleef* spleef;
	
		TCPsocket socket;
		IPaddress ip;
		SDLNet_SocketSet socketSet;		
		
		std::map<int, Client> clientList;
		std::stack<int> freeIDs;
		
		Config config;	
		Level map;
		
		bool map_save;
		std::string map_save_name;
		int map_save_ticks;
		int heartbeat_ticks;
		
		TCPsocket heartbeat_socket;
		
		struct block {
			int x, y, z, type; 
		};
		std::deque<block> block_queue;
		
		std::ofstream logFile;
		char ltime[15];
		
		int salt;
};

#endif
